PowerShellでSSMのポートフォワーディングを試してみた(けど駄目だったはなし)
【2023年4月追記】
未だ公式には対応してないものの、無理やり実現させることならできたので追記しておきます。
【追記ここまで】
しばたです。
先月のはなしなのですがAWS Systems Manager(以後SSM) セッションマネージャーにポートフォーワードの機能が追加され、Developers.IOでも以下の記事で紹介されています。
AWS公式の機能紹介はこちら。
このポートフォーワード機能は非常に便利で、以前私が書いた記事で紹介したRDP接続をSSHのポートフォーワードで行うことが踏み台となるSSHサーバー無しに実現可能になります。
- AWS Systems Manager セッションマネージャーで Windows 10 でSSH・SCPしてみた
- AWS Systems Manager セッションマネージャーで Windows Server 2019 にSSH・SCPしてみた
クライアント環境にAWS CLIとSession Manager Plugin for the AWS CLIをインストールしておけば、
# PowerShell コンソール上で実施する場合
$PROFILE_NAME = 'test-profile'
$INSTANCE_ID = '<your ec2 instance id>'
aws ssm start-session --target $INSTANCE_ID `
--document-name AWS-StartPortForwardingSession `
--parameters '{\"portNumber\":[\"3389\"],\"localPortNumber\":[\"13389\"]}' `
--profile $PROFILE_NAME
といったコマンド一発で踏み台無しにRDP接続することができます。
ご覧の通り非常に楽にRDP接続できます。
PowerShellでSSMのポートフォワーディングを試してみた
この機能はAWS CLIの利用が必須となっており、仕組みとしてはaws ssm start-session
コマンドがsession-manager-plugin
(Session Manager Plugin)を起動しプロセス間通信を経てSSMのエンドポイントにコネクションを張るものとなっています。
Windows環境においてですが、Process Explorerでポートフォーワード中のプロセスを見てると下図の様にaws.exe
がsession-manager-plugin.exe
を呼び出していることがわかります。
Start-SSMSession
ここでAWS Tools for PowerShellにはaws ssm start-session
コマンドと対になるStart-SSMSessionコマンドレットが存在します。
ただ、残念ながらこのコマンドレットはsession-manager-plugin
と連携することは無く、実行した結果は単純にSSMのセッション情報を返して終わります。
# Start-SSMSession はただセッション情報を返すだけ
Import-Module AWSPowerShell.NetCore
Set-DefaultAWSRegion -Region ap-northeast-1
Set-AWSCredential -ProfileName your-profile
$INSTANCE_ID = '<your ec2 instance id>'
$params = @{
Target = $INSTANCE_ID
DocumentName = 'AWS-StartPortForwardingSession';
Parameter = @{
portNumber = '3389'
localPortNumber = '13389'
};
}
$session = Start-SSMSession @params
$session | Format-List
(単純にセッション情報を返してコマンドレットは終了する)
session-manager-plugin の引数
Start-SSMSession単体ではsession-manager-plugin
を起動してくれないことがわかりましたので、どうにかsession-manager-plugin
を起動できないかとsession-manager-plugin
が取りうる引数を調べてみることにしました。
session-manager-plugin
はソースが公開されておらず、適当に引数を渡してみても役に立つ情報は得られませんでした。
そこで呼び出し元のAWS CLIのソースを読んでみたところ、
# sessionmanager.py のソースを一部抜粋
# call executable with necessary input
check_call(["session-manager-plugin",
json.dumps(response),
region_name,
"StartSession",
profile_name,
json.dumps(parameters),
endpoint_url])
と、
- 第1引数 : SSMセッション情報(JSON)の文字列
- 第2引数 : リージョン名
- 第3引数 : "StartSession"固定
- 第4引数 : プロファイル名 (プロファイル未指定の場合は '')
- 第5引数 : aws ssm start-sessionコマンドに渡したパラメーターをJSONにしたもの
- 第6引数 : SSMエンドポイントのURL
であることがわかりました。
ここで厄介なのが第4引数のプロファイル名で、こちらはAWS CLIで設定したプロファイル名をそのまま引き渡しており、session-manager-plugin
はAWS CLIと認証情報を共有しています。
仕組み上AWS Tools for PowerShellとAWS CLIは認証情報は別となっており相互に変換する機能はありません。どうにかAWS Tools for PowerShellで完結させたいと思うものの、AWS CLIの認証情報が必要となってしまうと素直にAWS CLIを使用するしかなく、また、そうするのが現実的です。
最後に
ざっとこんな感じでした。
タイトルに記載している様にAWS Tools for PowerShellを使いSSMのポートフォーワード機能を利用するのは現実的ではなく大人しくAWS CLIを利用したほうが良いことがわかりました。
今後AWS Tools for PowerShellまたはsession-manager-plugin側で何らかの機能更新がありPowerShellからSSMのポートフォーワード機能が使える様になるとPowerShellおじさんの私としては嬉しいのですが、おそらく、現実は厳しいままであると思います。